package com.bf.electroplating.service.impl;

import com.alibaba.excel.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bf.electroplating.mapper.MessageLogMapper;
import com.bf.electroplating.mapper.RainfallOutletMonitoringMapper;
import com.bf.electroplating.pojo.entity.*;
import com.bf.electroplating.service.*;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.*;
@Service
@Slf4j
public class MessageLogServiceImpl extends ServiceImpl < MessageLogMapper,MessageLog > implements MessageLogService {

    @Resource
    private IWasteGasMonitoringService  wasteGasMonitoringService;
    @Resource
    private IWasteGasMonitoringLogService wasteGasMonitoringLogService;
    @Resource
    private RainfallOutletMonitoringMapper rainfallOutletMonitoringService;
    @Resource
    private IRainfallOutletMonitoringLogService rainfallOutletMonitoringLogService;
    @Resource
    private IExhaustGasWarningService exhaustGasWarningService;
    @Resource
    private IEnterpriseOutfallValveInfoService enterpriseOutfallValveInfoService;
    @Resource
    private IEnterpriseOutfallValveService enterpriseOutfallValveService;
    @Resource
    private IEnterpriseOutfallValveAlarmService enterpriseOutfallValveAlarmService;
    @Resource
    private IParkOutletMonitoringService parkOutletMonitoringService;
    @Resource
    private IParkOutletMonitoringLogService parkOutletMonitoringLogService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void dateCheck(MessageLog messageLog) {
        log.info("记录到日志"+messageLog);
        this.save(messageLog);
        List<WasteGasMonitoring> wasteGasMonitoringList = wasteGasMonitoringService.list();
        List< RainfallOutletMonitoring> rainfallOutletMonitorings=rainfallOutletMonitoringService.selectList(new LambdaQueryWrapper<>());
        Map<String,String> valueMap=parseToMap(messageLog.getMessage());
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");
        Set<String> keys=valueMap.keySet();
        for (WasteGasMonitoring wasteGasMonitoring : wasteGasMonitoringList) {
            if (wasteGasMonitoring.getMnCode().equals(messageLog.getMn())) {
                if (!StringUtils.isEmpty(wasteGasMonitoring.getPhFlag())&&keys.contains(wasteGasMonitoring.getPhFlag())) {
                    BigDecimal phValue = new BigDecimal(valueMap.get(wasteGasMonitoring.getPhFlag()));
                    wasteGasMonitoring.setPhValue(phValue);
                    
                    // 检查PH值预警
                    exhaustGasWarningService.checkAndGenerateWarning(wasteGasMonitoring, phValue, "PH");
                }
                if (!StringUtils.isEmpty(wasteGasMonitoring.getOrpFlag())&&keys.contains(wasteGasMonitoring.getOrpFlag())) {
                    BigDecimal orpValue = new BigDecimal(valueMap.get(wasteGasMonitoring.getOrpFlag()));
                    wasteGasMonitoring.setOrpValue(orpValue);
                    
                    // 检查ORP值预警
                    exhaustGasWarningService.checkAndGenerateWarning(wasteGasMonitoring, orpValue, "ORP");
                }
                if (!StringUtils.isEmpty(valueMap.get("QN"))) {
                    wasteGasMonitoring.setMonitoringTime(LocalDateTime.parse(valueMap.get("QN"), formatter));
                }
                wasteGasMonitoringService.updateById(wasteGasMonitoring);
                WasteGasMonitoringLog wasteGasMonitoringLog=new WasteGasMonitoringLog();
                BeanUtils.copyProperties(wasteGasMonitoring,wasteGasMonitoringLog);
                wasteGasMonitoringLog.setId(null);
                wasteGasMonitoringLog.setLogTime(LocalDateTime.now());
                wasteGasMonitoringLog.setParkId("1001");
                wasteGasMonitoringLog.setCompanyId(wasteGasMonitoring.getCompanyId());
                wasteGasMonitoringLog.setMonitoringId(wasteGasMonitoring.getId());
                wasteGasMonitoringLogService.save(wasteGasMonitoringLog);
            }
        }
        for (RainfallOutletMonitoring rainfallOutletMonitoring : rainfallOutletMonitorings) {
            if (rainfallOutletMonitoring.getMnCode().equals(messageLog.getMn())) {
                if(!StringUtils.isEmpty(valueMap.get(rainfallOutletMonitoring.getEmergencyPoolLevelFlag()))) {
                    rainfallOutletMonitoring.setEmergencyPoolLevel(new BigDecimal(valueMap.get(rainfallOutletMonitoring.getEmergencyPoolLevelFlag())));
                }
                if(!StringUtils.isEmpty(valueMap.get(rainfallOutletMonitoring.getEmergencyPoolLevelFlag()))) {
                    rainfallOutletMonitoring.setRainOutletLevel(new BigDecimal(valueMap.get(rainfallOutletMonitoring.getRainOutletLevelFlag())));
                }
                if ("1.00".equals(valueMap.get(rainfallOutletMonitoring.getEmergencyPoolValveStatusFlag()))||"1".equals(valueMap.get(rainfallOutletMonitoring.getEmergencyPoolValveStatusFlag()))) {
                    rainfallOutletMonitoring.setEmergencyPoolValveStatus("1");
                }else {
                    rainfallOutletMonitoring.setEmergencyPoolValveStatus("0");
                }
                if ("1.00".equals(valueMap.get(rainfallOutletMonitoring.getRainOutletValveStatusFlag()))||"1".equals(valueMap.get(rainfallOutletMonitoring.getRainOutletValveStatusFlag()))) {
                    rainfallOutletMonitoring.setRainOutletValveStatus("1");
                }else {
                    rainfallOutletMonitoring.setRainOutletValveStatus("0");
                }
                if (!StringUtils.isEmpty(valueMap.get("QN"))) {
                    rainfallOutletMonitoring.setMonitoringTime(LocalDateTime.parse(valueMap.get("QN"), formatter));
                }
                rainfallOutletMonitoringService.updateById(rainfallOutletMonitoring);
                RainfallOutletMonitoringLog rainfallOutletMonitoringLog=new RainfallOutletMonitoringLog();
                BeanUtils.copyProperties(rainfallOutletMonitoring,rainfallOutletMonitoringLog);
                rainfallOutletMonitoringLog.setId(null);
                rainfallOutletMonitoringLog.setCompanyId(rainfallOutletMonitoring.getCompanyId());
                rainfallOutletMonitoringLog.setLogTime(LocalDateTime.now());
                rainfallOutletMonitoringLog.setParkId("1001");
                rainfallOutletMonitoringLog.setMonitoringId(rainfallOutletMonitoring.getId());
                rainfallOutletMonitoringLogService.save(rainfallOutletMonitoringLog);
            }
        }
        
        // 处理企业排污阀数据
        processEnterpriseOutfallValve(messageLog, valueMap, formatter);
        
        // 处理园区排口监控数据
        processParkOutletMonitoring(messageLog, valueMap, formatter);
    }
    
    /**
     * 处理企业排污阀监测数据
     */
    private void processEnterpriseOutfallValve(MessageLog messageLog, Map<String, String> valueMap, DateTimeFormatter formatter) {
        try {
            // 查询所有排污阀基础信息
            List<EnterpriseOutfallValveInfo> valveInfoList = enterpriseOutfallValveInfoService.list(
                    new LambdaQueryWrapper<EnterpriseOutfallValveInfo>()
                            .eq(EnterpriseOutfallValveInfo::getStatus, "1")
                            .eq(EnterpriseOutfallValveInfo::getDelFlag, "0")
            );
            
            for (EnterpriseOutfallValveInfo valveInfo : valveInfoList) {
                // 根据MN码匹配设备
                if (!valveInfo.getMnCode().equals(messageLog.getMn())) {
                    continue;
                }
                //似乎不是所有申报都会有此类数据，没有就别入库了
                if (!valueMap.containsKey("w21011-Avg")){
                    continue;
                }
                
                log.info("处理企业排污阀数据：MN={}, 设备名称={}", valveInfo.getMnCode(), valveInfo.getDeviceName());
                
                // 创建监测数据记录
                EnterpriseOutfallValve valve = new EnterpriseOutfallValve();
                valve.setId(UUID.randomUUID().toString().replace("-", ""));
                valve.setCompanyId(valveInfo.getCompanyId());
                valve.setCompanyName(valveInfo.getCompanyName());
                valve.setParkId(valveInfo.getParkId());
                valve.setOutfallId(valveInfo.getOutfallId());
                valve.setDeviceName(valveInfo.getDeviceName());
                valve.setDeviceCode(valveInfo.getDeviceCode());
                valve.setMnCode(valveInfo.getMnCode());
                valve.setDeviceType(valveInfo.getDeviceType());
                //##0319QN=20251010091100029;ST=32;CN=2011;PW=123456;MN=88888880000001;Flag=4;CP=&&DataTime=20251010091100;w01018-Rtd=49.711,w01018-Flag=N;w20116-Rtd=0.004,w20116-Flag=N;w21001-Rtd=11.203,w21001-Flag=N;w20123-Rtd=0.000,w20123-Flag=B;w21011-Rtd=0.000,w21011-Flag=B;w20122-Rtd=0.000,w20122-Flag=B;w21003-Rtd=0.973,w21003-Flag=N&&53C0
                // 解析监测时间
                if (!StringUtils.isEmpty(valueMap.get("QN"))) {
                    valve.setMonitoringTime(LocalDateTime.parse(valueMap.get("QN"), formatter));
                }
                if (!StringUtils.isEmpty(valueMap.get("DataTime"))) {
                    DateTimeFormatter dataTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
                    valve.setDataTime(LocalDateTime.parse(valueMap.get("DataTime"), dataTimeFormatter));
                }


                parseFactorData(valueMap, "w00000", valve, "flowRate");
                // 化学需氧量 （w01018）
                parseFactorData(valueMap, "w01018", valve, "cod");


                // 解析PH值数据（w01001）
                parseFactorData(valueMap, "w01001", valve, "ph");
                
                // 解析总铬数据（w21001）
                parseFactorData(valueMap, "w20116", valve, "totalChromium");

                // 解析总氮数据（w21001）
                parseFactorData(valueMap, "w21001", valve, "totalNitrogen");
                // 解析总磷数据（w21001）
                parseFactorData(valueMap, "w21011", valve, "totalPhosphorus");
                // 解析总铜数据（w21001）
                parseFactorData(valueMap, "w20122", valve, "totalCopper");
                // 解析氨氮数据（w21001）
                parseFactorData(valueMap, "w21003", valve, "ammoniaNitrogen");


                // 解析氨氮数据（w20123）
                parseFactorData(valueMap, "w20123", valve, "totalZinc");


                // 设置在线状态
                valve.setOnlineStatus("1");
                valveInfo.setOnlineStatus("1");
                
                // 设置默认值
                valve.setStatus("1");
                valve.setDelFlag("0");
                valve.setCreateTime(LocalDateTime.now());
                valve.setUpdateTime(LocalDateTime.now());
                
                // 保存监测数据
                enterpriseOutfallValveService.save(valve);
                log.info("保存企业排污阀监测数据成功：ID={}", valve.getId());
                
                // 更新基础信息表的在线状态和当前状态
                enterpriseOutfallValveInfoService.updateById(valveInfo);
                
                // 检查并生成告警

            }
        } catch (Exception e) {
            log.error("处理企业排污阀数据失败：{}", e.getMessage(), e);
        }
    }
    
    /**
     * 处理园区排口监控数据
     */
    private void processParkOutletMonitoring(MessageLog messageLog, Map<String, String> valueMap, DateTimeFormatter formatter) {
        try {
            log.info("开始处理园区排口监控数据，MN码：{}", messageLog.getMn());
            
            // 查询所有园区排口监控设备
            List<ParkOutletMonitoring> parkOutletList = parkOutletMonitoringService.list(
                    new LambdaQueryWrapper<ParkOutletMonitoring>()
                            .eq(ParkOutletMonitoring::getMnCode, messageLog.getMn())
                            .eq(ParkOutletMonitoring::getDelFlag, "0")
            );
            
            if (parkOutletList.isEmpty()) {
                log.debug("未找到匹配的园区排口监控设备，MN码：{}", messageLog.getMn());
                return;
            }
            
            log.info("找到{}个匹配的园区排口监控设备", parkOutletList.size());
            
            for (ParkOutletMonitoring parkOutlet : parkOutletList) {
                String monitoringFactorCode = parkOutlet.getMonitoringFactorCode();
                if (StringUtils.isEmpty(monitoringFactorCode)) {
                    log.warn("园区排口监控设备监测因子编码为空，跳过处理：设备名称={}", parkOutlet.getDeviceName());
                    continue;
                }
                
                // 根据监测因子编码查找对应的数据
                // 例如：monitoringFactorCode为"PH"，查找"PH-Rtd"字段
                String rtdKey = monitoringFactorCode + "-Rtd";
                
                if (!valueMap.containsKey(rtdKey)) {
                    log.debug("未找到对应的监测数据，监测因子：{}，MN码：{}", monitoringFactorCode, messageLog.getMn());
                    continue;
                }
                
                log.info("处理园区排口监控数据：设备名称={}，监测因子={}，数据值={}", 
                        parkOutlet.getDeviceName(), monitoringFactorCode, valueMap.get(rtdKey));
                
                // 更新监测数据
                try {
                    BigDecimal newValue = new BigDecimal(valueMap.get(rtdKey));
                    parkOutlet.setValueNew(newValue);
                    
                    // 更新监测时间
                    if (!StringUtils.isEmpty(valueMap.get("QN"))) {
                        parkOutlet.setMonitoringTime(LocalDateTime.parse(valueMap.get("QN"), formatter));
                    }
                    
                    // 设置设备状态为在线
                    parkOutlet.setStatus("1");
                    parkOutlet.setUpdateTime(LocalDateTime.now());
                    
                    // 保存更新后的数据
                    parkOutletMonitoringService.updateById(parkOutlet);
                    
                    // 创建日志记录
                    ParkOutletMonitoringLog logRecord = new ParkOutletMonitoringLog();
                    BeanUtils.copyProperties(parkOutlet, logRecord);
                    logRecord.setId(null); // 清空ID，让数据库自动生成
                    logRecord.setLogTime(LocalDateTime.now());
                    logRecord.setCreateTime(LocalDateTime.now());
                    logRecord.setMonitoringId(parkOutlet.getOutletId());
                    logRecord.setMonitoringValue(newValue);
                    // 保存日志记录
                    parkOutletMonitoringLogService.save(logRecord);
                    
                    log.info("园区排口监控数据更新成功：设备名称={}，监测因子={}，数值={}", 
                            parkOutlet.getDeviceName(), monitoringFactorCode, newValue);
                    
                } catch (NumberFormatException e) {
                    log.error("解析监测数值失败：监测因子={}，数值={}，错误：{}", 
                            monitoringFactorCode, valueMap.get(rtdKey), e.getMessage());
                } catch (Exception e) {
                    log.error("更新园区排口监控数据失败：设备名称={}，监测因子={}，错误：{}", 
                            parkOutlet.getDeviceName(), monitoringFactorCode, e.getMessage(), e);
                }
            }
            
        } catch (Exception e) {
            log.error("处理园区排口监控数据失败：{}", e.getMessage(), e);
        }
    }
    
    /**
     * 解析HJ212因子数据（Min/Max/Avg/Cou/Flag）
     * 
     * @param valueMap 报文数据Map
     * @param factorCode 因子编码（如：w01018）
     * @param valve 排污阀对象
     * @param fieldPrefix 字段前缀（如：flowRate）
     */
    private void parseFactorData(Map<String, String> valueMap, String factorCode, 
                                  EnterpriseOutfallValve valve, String fieldPrefix) {
        try {
            String minKey = factorCode + "-Min";
            String maxKey = factorCode + "-Max";
            String avgKey = factorCode + "-Avg";
            String couKey = factorCode + "-Cou";
            String flagKey = factorCode + "-Flag";
            
            if (!StringUtils.isEmpty(valueMap.get(minKey))) {
                String methodName = "set" + capitalize(fieldPrefix) + "Min";
                java.lang.reflect.Method method = EnterpriseOutfallValve.class.getMethod(methodName, BigDecimal.class);
                method.invoke(valve, new BigDecimal(valueMap.get(minKey)));
            }
            
            if (!StringUtils.isEmpty(valueMap.get(maxKey))) {
                String methodName = "set" + capitalize(fieldPrefix) + "Max";
                java.lang.reflect.Method method = EnterpriseOutfallValve.class.getMethod(methodName, BigDecimal.class);
                method.invoke(valve, new BigDecimal(valueMap.get(maxKey)));
            }
            
            if (!StringUtils.isEmpty(valueMap.get(avgKey))) {
                String methodName = "set" + capitalize(fieldPrefix) + "Avg";
                java.lang.reflect.Method method = EnterpriseOutfallValve.class.getMethod(methodName, BigDecimal.class);
                method.invoke(valve, new BigDecimal(valueMap.get(avgKey)));
            }
            
            if (!StringUtils.isEmpty(valueMap.get(couKey))) {
                String methodName = "set" + capitalize(fieldPrefix) + "Cou";
                java.lang.reflect.Method method = EnterpriseOutfallValve.class.getMethod(methodName, BigDecimal.class);
                method.invoke(valve, new BigDecimal(valueMap.get(couKey)));
            }
            
            if (!StringUtils.isEmpty(valueMap.get(flagKey))) {
                String methodName = "set" + capitalize(fieldPrefix) + "Flag";
                java.lang.reflect.Method method = EnterpriseOutfallValve.class.getMethod(methodName, String.class);
                method.invoke(valve, valueMap.get(flagKey));
            }
            
        } catch (Exception e) {
            log.error("解析因子数据失败：factorCode={}, fieldPrefix={}, 错误：{}", factorCode, fieldPrefix, e.getMessage());
        }
    }
    
    /**
     * 首字母大写
     */
    private String capitalize(String str) {
        if (str == null || str.isEmpty()) {
            return str;
        }
        return str.substring(0, 1).toUpperCase() + str.substring(1);
    }

    public static void main(String[] args) {
        String msg = "##0194QN=20250823113000015;ST=27;CN=2011;PW=123456;MN=82520039;Flag=4;CP=&&DataTime=20250823113000;CQCYW-Rtd=3,CQCYW-Flag=N;YJCYW-Rtd=32,YJCYW-Flag=N;YJFM-Rtd=0,YJFM-Flag=N;PKFM-Rtd=0.00,PKFM-Flag=N&&59C0";

        Parsed result = parse(msg);

        System.out.println("前校验位: " + result.frontCheck);
        System.out.println("后校验位: " + result.rearCheck);

        System.out.println("主体字段:");
        result.headerFields.forEach((k, v) -> System.out.println("  " + k + " = " + v));

        System.out.println("CP字段:");
        result.cpFields.forEach((k, v) -> System.out.println("  " + k + " = " + v));
    }

    public static  Map<String,String> parseToMap(String msg){
        Parsed result=parse(msg);
        Map<String,String> map=new HashMap<>();
        map.putAll(result.headerFields);
        map.putAll(result.cpFields);
        return map;
    }
    public static Parsed parse(String msg) {
        if (msg == null || msg.isEmpty()) {
            log.warn("报文为空，返回空解析结果");
            return new Parsed("", "", new LinkedHashMap<>(), new LinkedHashMap<>());
        }

        String frontCheck = "";
        String rearCheck = "";
        Map<String, String> headerFields = new LinkedHashMap<>();
        Map<String, String> cpFields = new LinkedHashMap<>();

        try {
            // 1) 尝试定位 QN= 字段，如果不存在则从开头开始解析
            int qnIdx = msg.indexOf("QN=");
            if (qnIdx > 0) {
                // 找到QN字段，前校验位是从开头到QN=之前
                frontCheck = msg.substring(0, qnIdx);
            } else {
                // 未找到QN字段，尝试从开头解析
                log.warn("未找到 QN= 字段，尝试从开头解析报文: {}", msg);
                qnIdx = 0;
            }

            // 2) 定位 CP 内容的起止位置：CP=&& ... &&
            int cpStart = msg.indexOf("CP=&&", qnIdx);
            if (cpStart < 0) {
                log.warn("未找到 CP=&& 起始标记，尝试解析整个报文作为头部字段: {}", msg);
                // 如果没有CP段，尝试将整个剩余部分作为头部字段解析
                String remainingPart = msg.substring(qnIdx);
                headerFields = parseHeader(remainingPart);
                return new Parsed(frontCheck, rearCheck, headerFields, cpFields);
            }

            int cpContentStart = cpStart + "CP=&&".length();
            int cpContentEnd = msg.indexOf("&&", cpContentStart);
            if (cpContentEnd < 0) {
                log.warn("未找到 CP 结束标记 &&，尝试解析到字符串末尾: {}", msg);
                // 如果没有结束标记，尝试解析到字符串末尾
                cpContentEnd = msg.length();
            }

            // 3) 后校验位：在 CP 结束 && 之后到字符串末尾
            if (cpContentEnd < msg.length()) {
                rearCheck = msg.substring(cpContentEnd + 2);
            }

            // 4) 头部字段：在 QN= 之后，直到 CP=&& 之前（不包含 CP 段）
            if (qnIdx < cpStart) {
                String headerPart = msg.substring(qnIdx, cpStart);
                headerFields = parseHeader(headerPart);
            }

            // 5) CP 字段：取出 CP=&& 与结束 && 之间的完整内容，再拆分
            if (cpContentStart < cpContentEnd) {
                String cpContent = msg.substring(cpContentStart, cpContentEnd);
                cpFields = parseCP(cpContent);
                // 方便查看原始 CP 文本（可选）
                headerFields.put("CP(raw)", cpContent);
            }

        } catch (Exception e) {
            log.error("解析报文时发生异常: {}, 报文内容: {}", e.getMessage(), msg);
            // 即使解析失败，也返回已解析的部分
        }

        return new Parsed(frontCheck, rearCheck, headerFields, cpFields);
    }

    private static Map<String, String> parseHeader(String headerPart) {
        Map<String, String> map = new LinkedHashMap<>();
        String[] tokens = headerPart.split(";");
        for (String t : tokens) {
            if (t == null || t.isEmpty()) continue;
            String[] kv = t.split("=", 2);
            if (kv.length == 2) {
                map.put(kv[0].trim(), kv[1].trim());
            }
        }
        return map;
    }

    private static Map<String, String> parseCP(String cpContent) {
        Map<String, String> map = new LinkedHashMap<>();
        // CP 内：分号分组，再用逗号分成多个 key=value
        String[] groups = cpContent.split(";");
        for (String g : groups) {
            if (g == null || g.isEmpty()) continue;
            String[] pairs = g.split(",");
            for (String pair : pairs) {
                if (pair == null || pair.isEmpty()) continue;
                String[] kv = pair.split("=", 2);
                if (kv.length == 2) {
                    map.put(kv[0].trim(), kv[1].trim());
                }
            }
        }
        return map;
    }

    // 结果封装
    public static class Parsed {
        public final String frontCheck;
        public final String rearCheck;
        public final Map<String, String> headerFields;
        public final Map<String, String> cpFields;

        public Parsed(String frontCheck, String rearCheck,
                      Map<String, String> headerFields, Map<String, String> cpFields) {
            this.frontCheck = frontCheck;
            this.rearCheck = rearCheck;
            this.headerFields = headerFields;
            this.cpFields = cpFields;
        }
    }
}
